﻿using Microsoft.AspNetCore.Mvc;
using YL.NetCore.NetCoreApp;
using IServices;
using Microsoft.AspNetCore.Authorization;
using YL.Utils.Table;
using YL.Utils.Pub;
using SqlSugar;
using YL.Core.Entity;
using System.Threading.Tasks;
using YL.Utils.String;
using IdGen;
using YL.Core.Entity.Fluent.Validation;
using System.Linq;
using System;
using YL.Utils.Extensions;
using Microsoft.Extensions.Logging;
using RestSharp.Extensions;
using YL.Utils.Http;
using Senparc.CO2NET.Extensions;
using YL.Utils.Security;
using YL.Utils.Json;
using System.Data;
using Newtonsoft.Json.Linq;

namespace EduCMS.Controllers
{
    [Route("[controller]")]
    public class CourseController : BaseController 
    {
        private readonly IWhr_courseServices _courseServices;
        private readonly IWhr_commentServices _commentServices;
        private readonly IWhr_comment_imagesServices _commentImagesServices;
        private readonly IWhr_minio_fileServices _fileServices;
        private readonly SqlSugarClient _client;       

        public CourseController(
            SqlSugarClient client,
            IWhr_courseServices courseServices, 
            IWhr_commentServices commentServices, 
            IWhr_comment_imagesServices commentImagesServices, 
            IWhr_minio_fileServices fileServices)
        {
            _courseServices = courseServices;
            _commentServices = commentServices;
            _commentImagesServices = commentImagesServices;
            _client = client;
            _fileServices = fileServices;
        } 
        
        
        /// <summary>
        /// 课程搜索
        /// </summary>
        /// <param name="bootstrap"></param>
        /// <returns></returns>
        [HttpPost("all"), AllowAnonymous]
        public JsonResult Index([FromForm]Bootstrap.BootstrapParams bootstrap) 
        {
            var result = _courseServices.PageList(bootstrap);
            if (bootstrap.Lat != null && bootstrap.Lng != null) 
            {
                var address = "";
                var location = bootstrap.Lat + "," + bootstrap.Lng;
                var obj = _geoCoderTencentMapByLocation(location);
                
                if (!obj.IsNull()) 
                {
                    if (obj["status"].ToInt32() == 0) 
                    {
                        if (!obj["result"].IsNull() && !obj["result"]["address"].IsNull()) 
                        {
                            address = obj["result"]["formatted_addresses"]["recommend"].ToString();
                        }
                    }
                }
                var data = new {
                    rows = result.Item2,
                    address
                };
                return Json(Microprogram.DataInfo(PubEnum.Success, "", data));
            } 
            
            return Json(Microprogram.DataInfo(PubEnum.Success, "", Bootstrap.GridData(result.Item2, result.Item1)));
        }

        /// <summary>
        /// 我的课程列表
        /// </summary>
        /// <param name="bootstrap"></param>
        /// <returns></returns>
        [HttpPost("list")]
        public async Task<IActionResult> List([FromForm]Bootstrap.BootstrapParams bootstrap) 
        {
            var result = _courseServices.CoursePageList(UserDto.UserId, bootstrap);
            if (result.Item2 != null) 
            {
                var items = result.Item2;
                foreach (var item in items) 
                {
                    item.Logo = await _fileServices.GetObjectUrl(item.ObjectId);
                }
            }
            var data = new 
            {
                total = result.Item1,
                rows = result.Item2
            };
            return Json(Microprogram.DataInfo(PubEnum.Success, "", data));
        }

        /// <summary>
        /// 申请体验课程
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("apply")]
        public async Task<IActionResult> Apply([FromForm]Whr_course_apply dto) 
        {
            var courseInfo = await _client.Queryable<Whr_course>().Where(w => w.CourseId == dto.CourseId).FirstAsync();
            var studentInfo = await _client.Queryable<Whr_student>().Where(w => w.StudentId == dto.StudentId).FirstAsync();
            if (courseInfo is null || studentInfo is null) {
                return Json(Microprogram.DataInfo(PubEnum.Failed, "课程或学生不存在", null));
            }
            //已经体验过或者申请中的就不能再申请了
            var exits = await _client.Queryable<Whr_course_apply>().Where(w => w.CourseId == dto.CourseId && w.StudentId == dto.StudentId && (w.Status == 0 || w.Status == 1)).AnyAsync();
            if (exits) 
            {
                return Json(Microprogram.DataInfo(PubEnum.Failed, "您已申请课程，不能重复申请", null));
            }
            dto.UserId = UserDto.UserId;
            dto.Status = 0;
            dto.LeftTimes = courseInfo.SupportTimes;
            dto.Expire = 24 * 3600 * courseInfo.Expire;

            var result = await _client.Insertable(dto).ExecuteCommandAsync();
            if (result > 0)
            {
                return Json(Microprogram.DataInfo(PubEnum.Success, "添加成功", dto));
            }
            else {
                return Json(Microprogram.DataInfo(PubEnum.Error, "插入失败", null));
            }
        }

        /// <summary>
        /// 助力列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("support_list/{id}")]
        public IActionResult SupportList(int id) 
        {
            var applyInfo = _client.Queryable<Whr_course_apply, Whr_course>((ap, c) => new object[] {
                JoinType.Left, ap.CourseId == c.CourseId
            }).Select((ap, c) => new {
                ap.ApplyId,
                ap.CourseId,
                ap.StudentId,
                ap.CreateAt,
                ap.Status,
                ap.SupportTimes,
                ap.LeftTimes,
                Expire = ap.CreateAt + ap.Expire,
                c.CourseName,
                c.StartTime
            }).Where(w => w.CourseId == id).First();
            if (applyInfo == null) 
            {
                Json(Microprogram.DataInfo(PubEnum.Failed, "没有找到申请记录", null));
            }
            var supportList = _client.Queryable<Whr_support_records>().Where(w => w.ApplyId == applyInfo.ApplyId).ToList();
            var data = new { 
                apply_info = applyInfo,
                support_list = supportList
            };
            return Json(Microprogram.DataInfo(PubEnum.Success, "", data));
        }

        /// <summary>
        /// 点击助力时的操作
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("do_support")]
        public IActionResult DoSupport([FromForm]Whr_support_records dto) 
        {
            var validator = new SupportFluent();
            var results = validator.Validate(dto);
            var success = results.IsValid;
            if (success) 
            {
                var applyInfo = _client.Queryable<Whr_course_apply>().InSingle(dto.ApplyId);
                if (applyInfo == null) 
                {
                    return Json(Microprogram.DataInfo(PubEnum.Failed, "不存在此申请记录", null));
                }
                var userInfo = _client.Queryable<Whr_user>().InSingle(UserDto.UserId);

                dto.UserId = UserDto.UserId;
                dto.CourseId = applyInfo.CourseId;
                dto.Nickname = userInfo.Nickname;
                dto.Avatar = userInfo.Avatar;
                dto.Sex = userInfo.Sex;
                dto.CreateAt = DateTimeExt.GetUnixTimestamp();

                try
                {
                    _client.Ado.BeginTran();
                    //操作
                    _client.Updateable(applyInfo).UpdateColumns(it => new { it.LeftTimes }).ReSetValue(it => it.LeftTimes == (it.LeftTimes - 1)).ExecuteCommand();

                    _client.Insertable(dto);

                    _client.Ado.CommitTran();
                }
                catch (Exception ex) 
                {
                    _client.Ado.RollbackTran();
                    return Json(Microprogram.DataInfo(PubEnum.Failed, ex.Message, null));
                }
            }
            var msg = results.Errors.Aggregate("", (current, item) => current + item.ErrorMessage);
            return Json(Microprogram.DataInfo(PubEnum.Failed, msg, new { }));
        }

        
        /// <summary>
        /// 课程详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("detail/{Id}"), AllowAnonymous]
        public async Task<IActionResult> Detail(int id) 
        {
            var courseInfo = _client.Queryable<Whr_course>().Where(w => w.CourseId == id).First();
            if (courseInfo == null) 
            {
                return Json(Microprogram.DataInfo(PubEnum.Failed, "不存在此课程", null));
            }
            var applyNumber = _client.Queryable<Whr_course_apply>().Where(w => w.CourseId == id && w.Status == (int)ApplyStatus.Success).Count();
            
            var courseContent = _client.Queryable<Whr_course_content>().Where(w => w.Id == courseInfo.CourseContentId).First();
            var applyStatus = -1;
            if (UserDto != null) 
            {
                var applyInfo = _client.Queryable<Whr_course_apply>().Where(it => it.CourseId == id && it.UserId == UserDto.UserId).First();
                if (applyInfo != null) 
                {
                    applyStatus = applyInfo.Status;
                }
            }
            var data = new 
            {
                course = courseInfo,
                apply_number = applyNumber,
                content = courseContent,
                apply_status = applyStatus
            };
            await _client.Updateable<Whr_course>().SetColumns(it => it.ViewNumbers == (it.ViewNumbers + 1)).Where(it => it.CourseId == id).ExecuteCommandAsync();
            return Json(Microprogram.DataInfo(PubEnum.Success, "", data));
        }

        private object _geoCoderTencentMapByAddress(string address) 
        {
            address = EncoderUtil.UrlHttpUtilityEncoder(address);
            var str = HttpClientUtil.HttpGet(PubTXMap.Host + PubTXMap.GeoCoder + "?address=" + address + "&key=" + PubTXMap.Key, null);
            if (!str.IsNullOrEmpty()) 
            {
                return str.ToJson();
            }
            return null;
        }

        private JObject _geoCoderTencentMapByLocation(string location)
        {
            location = EncoderUtil.UrlHttpUtilityEncoder(location);
            var str = HttpClientUtil.HttpGet(PubTXMap.Host + PubTXMap.GeoCoder + "?location=" + location + "&key=" + PubTXMap.Key, null);
            if (!str.IsNullOrEmpty())
            {
                return str.ToJObject();
            }
            return null;
        }
    }
}